from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import QTimer, QEvent, QObject
from PySide6.QtGui import QIcon

import pygetwindow as gw

from src.ui_cursor_limit import Ui_MainWindow
from src.logo import get_icon
from src.Core import clip_cursor_wh
from src.debounce import debounce
from src import taskbar_icon_repair_magic
from src import fixdropshadow as fds
from src import Shortcut
from src.Config import Config
from src.getHWNDWithFileName import file2title


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.btn1.clicked.connect(self.btn1_clicked)
        self.ui.btn2.clicked.connect(self.btn2_clicked)
        self.ui.lineEdit_title.textChanged[str].connect(self.lineEdit_changed)
        self.ui.label_create_file.setOpenExternalLinks(False)
        self.ui.label_create_file.linkActivated.connect(self.create_config_file)

        #   0,待机;1,模式1;2,模式2
        self.running = 0

        self.config = Config()
        self.config.update()
        self.ui.spinBox_x.setValue(self.config.left)
        self.ui.spinBox_y.setValue(self.config.top)
        self.ui.spinBox_w.setValue(self.config.width)
        self.ui.spinBox_h.setValue(self.config.height)
        self.ui.lineEdit_title.setText(self.config.title)
        match self.config.mode:
            case 1:
                self.btn1_clicked()
            case 2:
                self.btn2_clicked()
        if self.config.startup == 0:
            Shortcut.DeleteStartupShortCut()
        else:
            Shortcut.CreateStartupShortCut()
        if file2title(self.config.filename) != "":
            self.ui.lineEdit_title.setText(file2title(self.config.filename))

        self.limit_posx = self.ui.spinBox_x.value()
        self.limit_posy = self.ui.spinBox_y.value()
        self.limit_width = self.ui.spinBox_w.value()
        self.limit_height = self.ui.spinBox_h.value()
        self.limit_centerX_shift = (
            self.limit_posx + self.limit_width // 2 - self.width() // 2
        )
        self.limit_centerY_shift = (
            self.limit_posy + self.limit_height // 2 - self.height() // 2
        )

        self.window_posx = 0
        self.window_posy = 0
        self.window_width = 0
        self.window_height = 0
        self.window_centerX_shift = 0
        self.window_centerY_shift = 0

        self.core_tick_runner = QTimer(self)
        self.core_tick_runner.timeout.connect(self.core_tick)
        self.core_tick_runner.start(1000 // self.config.tickrate)
        self.background_tick_runner = QTimer(self)
        self.background_tick_runner.timeout.connect(self.background_tick)
        self.background_tick_runner.start(100)

        self.reset_position = 270
        self.label_scroll_step = 8
        self.label_scroll1_posY = 0
        self.label_scroll2_posY = 65

    def btn1_clicked(self):
        match self.running:
            case 0 | 2:
                self.running = 1
                self.set_btn_text()
                self.update_data_mode1()
                # self.move(self.limit_centerX_shift, self.limit_centerY_shift)
                self.self_move_positive(
                    self.limit_centerX_shift, self.limit_centerY_shift
                )
            case 1:
                self.running = 0
                self.set_btn_text()
                clip_cursor_wh()  # 不提供参数，用于恢复正常的鼠标区域

    def btn2_clicked(self):
        match self.running:
            case 0 | 1:
                self.running = 2
                self.set_btn_text()
                # self.move(self.window_centerX_shift, self.window_centerY_shift)
            case 2:
                self.running = 0
                self.set_btn_text()
                clip_cursor_wh()  # 不提供参数，用于恢复正常的鼠标区域

    def set_btn_text(self):
        match self.running:
            case 0:
                self.ui.btn1.setText("启动")
                self.ui.btn2.setText("启动")
            case 1:
                self.ui.btn1.setText("停止")
                self.ui.btn2.setText("启动")
            case 2:
                self.ui.btn1.setText("启动")
                self.ui.btn2.setText("停止")

    # 防止传入负值，最低允许为0
    def self_move_positive(self, x, y):
        if x < 0:
            x = 0
        if y < 0:
            y = 0
        self.move(x, y)

    def core_tick(self):
        if self.running == 1:
            clip_cursor_wh(
                self.limit_posx, self.limit_posy, self.limit_width, self.limit_height
            )

        if self.running == 2:
            self.set_label5_text()
            self.update_data_mode2()
            self.self_move_positive(
                self.window_centerX_shift, self.window_centerY_shift
            )
            clip_cursor_wh(
                self.window_posx,
                self.window_posy,
                self.window_width,
                self.window_height,
            )

    def background_tick(self):
        if self.running == 1:
            self.ui.label_scroll1.move(
                self.ui.label_scroll1.x() - self.label_scroll_step,
                self.label_scroll1_posY,
            )
            if self.ui.label_scroll1.x() <= -self.reset_position:
                self.ui.label_scroll1.move(
                    self.ui.label_scroll1.x() + self.reset_position,
                    self.label_scroll1_posY,
                )

        if self.running == 2:
            self.ui.label_scroll2.move(
                self.ui.label_scroll2.x() - self.label_scroll_step,
                self.label_scroll2_posY,
            )
            if self.ui.label_scroll2.x() <= -self.reset_position:
                self.ui.label_scroll2.move(
                    self.ui.label_scroll2.x() + self.reset_position,
                    self.label_scroll2_posY,
                )

    def update_data_mode1(self):
        self.limit_posx = self.ui.spinBox_x.value()
        self.limit_posy = self.ui.spinBox_y.value()
        self.limit_width = self.ui.spinBox_w.value()
        self.limit_height = self.ui.spinBox_h.value()
        self.limit_centerX_shift = (
            self.limit_posx + self.limit_width // 2 - self.width() // 2
        )
        self.limit_centerY_shift = (
            self.limit_posy + self.limit_height // 2 - self.height() // 2
        )

    def update_data_mode2(self):
        """
        DwmGetWindowAttribute 和 GetWindowRect 一样，都会获得薛定谔的数据
        普通窗口(7077)
        API                     LEFT    TOP     RIGHT   BOTTOM
        GetWindowRect           120     89      1156    888
        DwmGetWindowAttribute   127     89      1149    881
        GDDDDDDG
        GDDDDDDG
        GDDDDDDG
        GGGGGGGG
        最大化(8888)
        (注:最大化也有7077模式(-8, -8, 1608, 908)(-1, -8, 1601, 901),然而显示器真实数据是1600*900,不知道这两个函数喝了多少，卧虫鸡雏)
        API                     LEFT    TOP     RIGHT   BOTTOM
        GetWindowRect           -8      -8      1928    1088
        DwmGetWindowAttribute   0       0       1920    1080
        GGGGGGGG
        GDDDDDDG
        GDDDDDDG
        GGGGGGGG
        最小化(7070)
        API                     LEFT    TOP     RIGHT   BOTTOM
        GetWindowRect           -32000  -32000  -31840  -31972
        DwmGetWindowAttribute   -31993  -32000  -31847  -31972
        GDDDDDDG
        GDDDDDDG
        GDDDDDDG
        GDDDDDDG
        """
        if self.ui.lineEdit_title.text() == "":
            self.reset_window_data()
            return

        windows = gw.getWindowsWithTitle(self.ui.lineEdit_title.text())
        if len(windows) == 0:
            self.reset_window_data()
            return

        w = windows[0]
        if w.isMinimized:
            self.reset_window_data()
            return

        shift1 = 0
        shift2 = 0
        shift3 = 0
        shift4 = 0
        # max 8888
        if w.isMaximized and (
            w.left + 8,
            w.top + 8,
            w.right - 8,
            w.bottom - 8,
        ) == fds.get_window_rect(w._hWnd):
            shift1 = 8
            shift2 = 8
            shift3 = -16
            shift4 = -16
        # max 7077
        if w.isMaximized and (
            w.left + 7,
            w.top,
            w.right - 7,
            w.bottom - 7,
        ) == fds.get_window_rect(w._hWnd):
            shift1 = 8
            shift2 = 8
            shift3 = -16
            shift4 = -16
        # normal 7077
        if (
            not w.isMaximized
            and not w.isMinimized
            and (w.left + 7, w.top, w.right - 7, w.bottom - 7)
            == fds.get_window_rect(w._hWnd)
        ):
            shift1 = 7
            shift2 = 0
            shift3 = -14
            shift4 = -7

        self.window_posx = w.left + shift1
        self.window_posy = w.top + shift2
        self.window_width = w.width + shift3
        self.window_height = w.height + shift4
        self.window_centerX_shift = (
            w.left + shift1 + (w.width + shift3) // 2 - self.width() // 2
        )
        self.window_centerY_shift = (
            w.top + shift2 + (w.height + shift4) // 2 - self.height() // 2
        )
        if self.window_centerX_shift < 0 or self.window_centerY_shift < 0:
            self.reset_window_data()

    def reset_window_data(self):
        self.window_posx = 0
        self.window_posy = 0
        self.window_width = 0
        self.window_height = 0
        self.window_centerX_shift = 0
        self.window_centerY_shift = 0

    @debounce(0.3)
    def lineEdit_changed(self, text):
        self.set_label5_text(text)

    def set_label5_text(self, text=""):
        if text == "":
            text = self.ui.lineEdit_title.text()
        check = len(gw.getWindowsWithTitle(text)) > 0 and text != ""

        if text == "":
            text = "*"
        elif self.ui.label_5.fontMetrics().boundingRect(text).width() > 96:
            text = text[:4] + "*" + text[-4:]

        if check:
            self.ui.label_5.setText("已检测到" + text + "窗口")
        else:
            self.ui.label_5.setText("未检测到" + text + "窗口")

    def create_config_file(self):
        self.config.create()

    def eventFilter(self, objwatched: QObject, event: QEvent):
        eventType = event.type()
        if eventType == QEvent.KeyPress and event.key() in [16777220, 16777221]:
            objName = objwatched.objectName()
            if objName.startswith("spinBox_") or objName == "btn1":
                self.btn1_clicked()
            elif objName == "lineEdit_title" or objName == "btn2":
                self.btn2_clicked()
        return super().eventFilter(objwatched, event)

def main():
    import sys

    taskbar_icon_repair_magic.magic()

    app = QApplication(sys.argv)
    window = MainWindow()
    window.setWindowIcon(QIcon(get_icon()))
    window.show()
    app.installEventFilter(window)
    sys.exit(app.exec())


if __name__ == "__main__":
    main()
